package com.opencv.demo;

import org.opencv.core.*;
import org.opencv.core.Core.MinMaxLocResult;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;

import java.io.File;

public class TemplateMaching {
    private String sourcePath, dstPath;
    private Mat source, dst;

    //原图片
    public void setSource(String picPath) {
        this.sourcePath = picPath;
    }

    //需要匹配的部分
    public void setDst(String picPath) {
        this.dstPath = picPath;
    }

    ///模版匹配，精确度不高
    public void process() {
        //将文件读入为OpenCV的Mat格式
        //source = HighGui.imread(sourcePath);
        String sourcePathParent = sourcePath.substring(0, sourcePath.lastIndexOf(File.separator));
        String fileName = sourcePath.substring(sourcePath.lastIndexOf(File.separator) + 1, sourcePath.length());
        String prefixName = fileName.substring(0, fileName.lastIndexOf("."));
        String suffixName = fileName.substring(fileName.lastIndexOf("."), fileName.length());


//        String dstPathParent = dstPath.substring(0, dstPath.lastIndexOf(File.separator));
//        String dstFileName = dstPath.substring(dstPath.lastIndexOf(File.separator) + 1, dstPath.length());
//        String dstPrefixName = dstFileName.substring(0, dstFileName.lastIndexOf("."));
//        String dstSuffixName = dstFileName.substring(dstFileName.lastIndexOf("."), dstFileName.length());


        //处理原图为灰度图
        source = Imgcodecs.imread(sourcePath);
//        Mat sourceGray = new Mat();
//        Imgproc.cvtColor(source, sourceGray, Imgproc.COLOR_BGR2GRAY, 0);
//        String sourceGrayPath = dstPathParent + File.separator + prefixName + "_gray" + suffixName;
//        Imgcodecs.imwrite(sourceGrayPath, sourceGray);

        dst = Imgcodecs.imread(dstPath);
//        Mat dstGray = new Mat();
//        Imgproc.cvtColor(dst, dstGray, Imgproc.COLOR_BGR2GRAY, 0);
//        String dstGrayPath = dstPathParent + File.separator + dstPrefixName + "_gray" + dstSuffixName;
//        Imgcodecs.imwrite(dstGrayPath, dstGray);


//        Mat sourceGrayMat = Imgcodecs.imread(sourceGrayPath);
//        Mat dstGrayMat = Imgcodecs.imread(dstGrayPath);
//        //创建于原图相同的大小，储存匹配度
//        Mat result = Mat.zeros(sourceGrayMat.rows(), sourceGrayMat.cols(), CvType.CV_32FC1);
//        //调用模板匹配方法
//        Imgproc.matchTemplate(sourceGrayMat, dstGrayMat, result, Imgproc.TM_SQDIFF);
//        //规格化
//        Core.normalize(result, result, 0, 1, Core.NORM_MINMAX, -1);
//        //获得最可能点，MinMaxLocResult是其数据格式，包括了最大、最小点的位置x、y
//        MinMaxLocResult mlr = Core.minMaxLoc(result);
//        Point matchLoc = mlr.minLoc;

        Mat result = Mat.zeros(source.rows(), source.cols(), CvType.CV_32FC1);
        //调用模板匹配方法
        Imgproc.matchTemplate(source, dst, result, Imgproc.TM_SQDIFF);
        //规格化
        Core.normalize(result, result, 0, 1, Core.NORM_MINMAX, -1);
        //获得最可能点，MinMaxLocResult是其数据格式，包括了最大、最小点的位置x、y
        MinMaxLocResult mlr = Core.minMaxLoc(result);
        Point matchLoc = mlr.minLoc;
        //在原图上的对应模板可能位置画一个绿色矩形
        Imgproc.rectangle(source, matchLoc, new Point(matchLoc.x + dst.width(), matchLoc.y + dst.height()), new Scalar(0, 255, 0));
        //将结果输出到对应位置
        String targetPath = sourcePathParent + File.separator + prefixName + "_target" + suffixName;
        Imgcodecs.imwrite(targetPath, source);
    }

    public static void main(String[] args) {
        System.loadLibrary("opencv_java341");

        TemplateMaching macher = new TemplateMaching();
        //设置原图
        macher.setSource("C:\\Users\\MPC\\Desktop\\git_test\\opencvdemo\\src\\main\\resources\\imgdata\\source1.jpg");
        //设置要匹配的图
        macher.setDst("C:\\Users\\MPC\\Desktop\\git_test\\opencvdemo\\src\\main\\resources\\imgdata\\dst_des2.png");

        //模版匹配
        //macher.process();

        //轮廓查找
        //macher.canny();

        macher.faceDetector("C:\\Users\\MPC\\Desktop\\git_test\\opencvdemo\\src\\main\\resources\\imgdata\\face2.jpeg");

    }

    /**
     * 查找轮廓
     */
    public void canny() {
        //将文件读入为OpenCV的Mat格式
        String sourcePathParent = sourcePath.substring(0, sourcePath.lastIndexOf(File.separator));
        String fileName = sourcePath.substring(sourcePath.lastIndexOf(File.separator) + 1, sourcePath.length());
        String prefixName = fileName.substring(0, fileName.lastIndexOf("."));
        String suffixName = fileName.substring(fileName.lastIndexOf("."), fileName.length());
        source = Imgcodecs.imread(sourcePath);
        int threshold = 300;
        Mat cannyDst = new Mat();
        Imgproc.cvtColor(source, cannyDst, Imgproc.COLOR_BGR2GRAY);
        Imgproc.Canny(source, cannyDst, threshold, threshold * 3, 3, true);
        String target1Path = sourcePathParent + File.separator + prefixName + "_canny" + suffixName;
        Imgcodecs.imwrite(target1Path, cannyDst);
    }

    /**
     * 人脸检测
     */
    public void faceDetector(String sourcePath) {
        //将文件读入为OpenCV的Mat格式
        String sourcePathParent = sourcePath.substring(0, sourcePath.lastIndexOf(File.separator));
        String fileName = sourcePath.substring(sourcePath.lastIndexOf(File.separator) + 1, sourcePath.length());
        String prefixName = fileName.substring(0, fileName.lastIndexOf("."));
        String suffixName = fileName.substring(fileName.lastIndexOf("."), fileName.length());

        CascadeClassifier faceDetector = new CascadeClassifier("C:\\Users\\MPC\\Desktop\\git_test\\opencvdemo\\src\\main\\resources\\haarcascade_frontalface_alt.xml");
        Mat image = Imgcodecs.imread(sourcePath);

        MatOfRect faceDetections = new MatOfRect();
        faceDetector.detectMultiScale(image, faceDetections);

        System.out.println(String.format("Detected %s faces", faceDetections.toArray().length));

        for (Rect rect : faceDetections.toArray()) {
            Imgproc.rectangle(image, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height),
                    new Scalar(0, 255, 0));
        }

        String filename = sourcePathParent + File.separator + prefixName + "_faces" + suffixName;
        System.out.println(String.format("Writing %s", filename));
        Imgcodecs.imwrite(filename, image);
    }
}